#include <config.h>
#include <board.h>
#include <init.h>
#include <os.h>
#include <bitmap.h>
#include <bitops.h>
#include <settings.h>
#include "ES8P508x.h"
#include "lib_config.h"
#include "device.h"
#include "printk.h"
#include "es8p508_relay.h"

static struct device relay_dev;

typedef struct
{
    GPIO_TYPE       port;
    GPIO_TYPE_PIN   pin;
} per_relay_t;

static per_relay_t relay_pin[] =
{
    {RELAY1_ON_PORT, RELAY1_ON_PIN},
	{RELAY1_OFF_PORT, RELAY1_OFF_PIN},
	{RELAY2_ON_PORT, RELAY2_ON_PIN},
	{RELAY2_OFF_PORT, RELAY2_OFF_PIN},
};
static void relay_num_detect(void)
{
    GPIO_InitStruType x;

    x.GPIO_Func = GPIO_Func_0;
    x.GPIO_Direction = GPIO_Dir_In;
    x.GPIO_PUEN = GPIO_PUE_Input_Enable;
    x.GPIO_PDEN = GPIO_PDE_Input_Disable;
    x.GPIO_OD   = GPIO_ODE_Output_Disable;
    
	int i = 0;
    for (i = 0; i < array_size(relay_pin); i++)
    {
        GPIO_Init(relay_pin[i].port, relay_pin[i].pin, &x);
    }
	
	for (i = 0; i < array_size(relay_pin); i++)
	{
		 if(!GPIO_ReadBit(relay_pin[i].port, relay_pin[i].pin))
		 {
			 dev_state.relay_num++;
			 dev_state.dev_type = ESTK_5A;
		 }
	}
	if(0x00 == dev_state.relay_num)
		dev_state.dev_type = ESTK;
	else if(dev_state.relay_num%2 == 0x00)
		dev_state.relay_num /= 2;
}
static void setup_relay_peri(per_relay_t *relay)
{
    GPIO_InitStruType x;

    x.GPIO_Func = GPIO_Func_0;
    x.GPIO_Direction = GPIO_Dir_Out;
    x.GPIO_PUEN = GPIO_PUE_Input_Enable;
    x.GPIO_PDEN = GPIO_PDE_Input_Disable;
    x.GPIO_OD   = GPIO_ODE_Output_Disable;
    GPIO_Init(relay->port, relay->pin, &x);
}

static void relay_gpio_init(void)
{ 
	int i;
    for (i = 0; i < array_size(relay_pin); i++)
    {
        setup_relay_peri(&relay_pin[i]);
		GPIO_ResetBit(relay_pin[i].port, relay_pin[i].pin);
    }
}

static void relay_on(uint8_t chn)
{
	int i;
	for(i = 0; i < dev_state.relay_num; i++)
	{
		if(tst_bit(chn,i))
		{
			SET_PIN_H(relay_pin[2*i].port, relay_pin[2*i].pin);//ON_PIN
			SET_PIN_L(relay_pin[2*i + 1].port, relay_pin[2*i + 1].pin);//OFF_PIN
			setting.dev_infor.opt_cnt[i]++;
			dev_state.param_save = 0x01;
		}
	}
}
static void relay_off(uint8_t chn)
{
	int i;
	for(i = 0; i < dev_state.relay_num; i++)
	{
		if(tst_bit(chn,i))
		{
			SET_PIN_L(relay_pin[2*i].port, relay_pin[2*i].pin);
			SET_PIN_H(relay_pin[2*i + 1].port, relay_pin[2*i + 1].pin);
			setting.dev_infor.opt_cnt[i]++;
			dev_state.param_save = 0x01;
		}
	}
}
static void relay_normal(uint8_t chn)
{
	int i;
	for(i = 0; i < dev_state.relay_num; i++)
	{
		if(tst_bit(chn,i))
		{
			SET_PIN_L(relay_pin[2*i].port, relay_pin[2*i].pin);
			SET_PIN_L(relay_pin[2*i + 1].port, relay_pin[2*i + 1].pin);
		}
	}
}

static err_t relay_ctrl(device_t *dev, uint8_t cmd, void *args)
{
    uint8_t *chn = (uint8_t *)args;
	
	switch (cmd)
    {
    case CTRL_RELAY_ON:
		relay_on(*chn);
		break;
	case CTRL_RELAY_OFF:
		relay_off(*chn);
		break;
	case CTRL_RELAY_NORMAL:
		relay_normal(*chn);
		break;
	default:
		break;
    }
    return 0;
}
static struct device_ops relay_ops =
{
	.ctrl = relay_ctrl,
};

int board_setup_relay(void)
{
    relay_num_detect();
	
	relay_gpio_init();

    relay_dev.ops = &relay_ops;
    device_register(&relay_dev, "relay", 0);

    return 0;
}
device_initcall(board_setup_relay);

